package com.devin.aop;

import com.devin.controller.LogController;
import com.devin.pojo.LogLogin;
import com.devin.service.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

@Component
@Aspect
public class LogAspect {

    private Date visitTime;

    @Autowired
    private  HttpServletRequest request;  /*从监听器里面获得的，项目没有启动就不会报错了*/

    @Autowired
    private LogService logService;


    @Before("execution(* com.devin.controller.*.* (..))")
    public void visitBefore(JoinPoint jp){
        visitTime = new Date();
    }

    @After("execution(* com.devin.controller.*.* (..))")
    public void visitAfter(JoinPoint jp) throws NoSuchMethodException {
        Class<?> methodClass = jp.getTarget().getClass();   /*获取方法对应的class*/
        if(methodClass== LogController.class){return;}

        LogLogin log = new LogLogin();
        /*获取登陆的用户名*/
        SecurityContext context = SecurityContextHolder.getContext();
        User principal = (User)context.getAuthentication().getPrincipal();
        String username = principal.getUsername();
        log.setUsername(username);

        /*持续时间*/
        Date endTime = new Date();
        Long duration = endTime.getTime()-visitTime.getTime();
        log.setDuration(duration);
        log.setVisitTime(visitTime);

        /*ip*/
        String ip = request.getRemoteAddr();
        log.setIp(ip);

        /*获得方法名*/
        String methodName = jp.getSignature().getName();
        log.setMethod(methodName);

        RequestMapping annotationClass = methodClass.getAnnotation(RequestMapping.class);
        String[] classUrls = annotationClass.value();   /*class对应的url*/

        Method method =null;
        Object[] args = jp.getArgs();
        if(args ==null || args.length==0){
            method = methodClass.getMethod(methodName);  /*无参方法对象*/
        }else{
            /*获取有参数方法对象*/
            Class[] classes = new Class[args.length];
            for(int i=0;i<args.length;i++){
                classes[i]=args[i].getClass();
            }
            method= methodClass.getMethod(methodName,classes);
        }

        RequestMapping annotationMethod = method.getAnnotation(RequestMapping.class);
        String[] methodUrls = annotationMethod.value();     /*method注解上url*/

        /*url*/
        String url =classUrls[0]+ methodUrls[0];
        log.setUrl(url);
        /*保存*/
        logService.saveLog(log);

    }

}
